package org.onejava.core.manage;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.onejava.core.annotation.IAop;
import org.onejava.core.annotation.ServiceInfo;
import org.onejava.core.aop.CglibProxy;
import org.onejava.core.aop.DynamicProxy;
import org.onejava.core.bean.Allconfig;
import org.onejava.core.bean.ServiceEntity;
import org.onejava.core.tools.ObjectTools;
import org.onejava.core.tools.ScanTool;


/**
 * @author frost
 *
 */
public class ServiceManage extends BaseManage{
	private static ServiceManage manage;
	private HashMap<String,ServiceEntity> entityMap;
	private static  Log log = LogFactory.getLog(ServiceManage.class);
	 
	private ServiceManage(){}
	
	/**
	 * 获取单例
	 * @return
	 */
	public static ServiceManage getMamage(){
    	if(null==manage){
    		manage = new  ServiceManage();
		}
		return manage;
    }
	public  ServiceEntity getService(String name) throws Exception{
		return entityMap.get(name);
	}
	
	public void intiMap(String packagePath) throws Exception{
		if(null!=entityMap){
			return;
		}
		//扫描出所有Service路径
		List<String> list = scan(packagePath);
		log.info("开始在路径<"+packagePath+">下扫描Service");
		entityMap = new HashMap<String, ServiceEntity>();
		//第一次循环，加载完成整个ServiceEntity，但是不包括为其注入其他service
		firstCycle(list);
		//第二次循环，所有service注入其他service
		secondCycle();
	}

	/**
	 * 第二次循环，每个service都尝试注入其他的service
	 * @throws Exception
	 */
	private void secondCycle() throws Exception {
		for (Entry<String, ServiceEntity> entry : entityMap.entrySet()) {
			   ServiceEntity entity = entry.getValue();
			   setService(entity);
		}
	}

	/**
	 * 第一次循环：
	 * 1.根据路径获取service和service的注解信息
	 * 2.创建一个ServiceEntity，放入service实例化的对象
	 * 3.通过AopManage和service中的方法获取每个方法的AOP链，放入ServiceEntity中
	 * 4.注入Spring的Bean
	 * 5.如果service的方法上有AOP的注解，则把这个service实例化的对象转化为动态代理对象
	 * @param list
	 * @throws Exception
	 */
	private void firstCycle(List<String> list) throws Exception {
		for(int i=0;i<list.size();i++){
			Class<?> theClass =  ObjectTools.getTheClass(list.get(i));
			Map map =getServiceInfo(theClass);
			if(map.isEmpty()){
				continue;
			}
			AopManage am = AopManage.getMamage();
			Object obj = ObjectTools.getTheObject(theClass);
			ServiceEntity se = new ServiceEntity((String) map.get("name"),obj);
			Method[] methods = theClass.getMethods();
			//校验和创建方法映射
			se.setNeedAop(buildMethods(am, se, methods));
			setBean(se);
			if(null!=entityMap.put((String) map.get("name"), se)){
				throw new Exception("Service:Name:"+map.get("name")+">>>ClassPath:"+list.get(i)+"有重复 Service加载STOP");
			}
			//如果需要转化为AOP代理对象，则转化
			if(se.isNeedAop()){
				se.setObj(new CglibProxy().bind(se,se.getObj()));
			}
		}
	}

	/**
	 * 判断是否需要为一个service创建AOP动态代理，并且把类的AOP方法中的AOP链提取出，
	 * 转换为MethodEntity存入ServiceEntity中
	 * @param am
	 * @param se
	 * @param methods
	 * @return
	 * @throws Exception
	 */
	private Boolean buildMethods( AopManage am, ServiceEntity se,
			Method[] methods) throws Exception {
		Boolean needAop =false;
		int x = methods.length;
		for(int j = 0;j<x;j++){
			Map methodMap = getMethodInfo(methods[j]);
			if(methodMap.size()==0){
				continue;
			}
			String after = (String) methodMap.get("after");
			String afterReturn = (String) methodMap.get("afterReturn");
			String afterThrow = (String) methodMap.get("afterThrow");
			String before = (String) methodMap.get("before");
			
			String[] afters = after.split(",");
			String[] afterReturns = afterReturn.split(",");
			String[] afterThrows = afterThrow.split(",");
			String[] befores = before.split(",");
			if(!"".equals(after)||!"".equals(afterReturn)||!"".equals(afterThrow)||!"".equals(before)){
				needAop=true;
			}
			se.putMethodEntity(methods[j], am.getAopChain(afters), 
					am.getAopChain(afterReturns), am.getAopChain(afterThrows), am.getAopChain(befores));
		}
		return needAop;
	}
	
	private Map getMethodInfo(Method method){
		IAop annotation = method.getAnnotation(IAop.class);
		Map<String ,String> map  = new HashMap<String ,String>();
		if(null!=annotation){
			String after=annotation.after();
			String afterReturn=annotation.afterReturn();
			String afterThrow=annotation.afterThrow();
			String before=annotation.before();
			map.put("after", after);
			map.put("afterReturn", afterReturn);
			map.put("afterThrow", afterThrow);
			map.put("before", before);
		}
		return map;		
	}
	
	
	/**
	 * 获取Service的注解信息
	 * @param theClass
	 * @return
	 */
	private Map getServiceInfo(Class<?> theClass){
		ServiceInfo annotation = theClass.getAnnotation(ServiceInfo.class);
		Map<String ,String> map  = new HashMap<String ,String>();
		if(null!=annotation){
			String name = annotation.name();
			map.put("name", name);
		}else{
		}
		return map;
	} 
	
}
